(* ================================================================== *)
(** Module I/O de gestion d'array à 2 dimensions de booléens.
    (exemple, les memoires ram, rom, etc ... *)
(* ================================================================== *)

open BitReader

(* ================================================================== *)
(** Créer une nouvelle matrice a partir d'une fonction de parcours des 
    cases linéairement de gauche à droite puis de haut en bas 
    @param dimx la 1ère dimension 
    @param dimy la 2ème dimenstion
    @param fct une fonction index dans la matrice -> 'a 
    @return m une matrice (dimx, dimy) fraiche, remplie avec fct *)
(* ================================================================== *)
let init_matrix_linear dimx dimy fct = 
  let t = Array.make dimx [||] in
  for i = 0 to pred dimx do
    t.(i) <- Array.init dimy (fun j -> fct (i * dimy + j))
  done;
  t
(* ================================================================== *)


(* ===================================================================== *)
(** Etant donné un bool array, il faut le découper en mots correspondant
    aux valeurs des mots d'une ram. Si le code est trop court, le reste 
    est mis a false. 
    @param taille le nombre de cases mémoire souhaitée
    @param lg_mot la longueur des mots mémoires en nombre de bit
    @param code un tableau à une dimension 
    @return m une matrice mémoire fraiche contenant les bits de code découpés
    selon le format demandé *)
(* ===================================================================== *)
let of_bool_array taille lg_mot code = 
  let len_donnee = Array.length code in
  let ff i = 
    if i < len_donnee
    then code.(i)
    else false
  in init_matrix_linear taille lg_mot ff

(* ===================================================================== *)
(** Lire une matrice bool dans un <b><i>fichier binaire</b></i> 
    @param taille le nombre de cases mémoire souhaitée
    @param lg_mot la longueur des mots mémoires en nombre de bit
    @param filename le nom du fichier binaire contenant les bits
    @return m une matrice mémoire fraiche contenant les bits du fichier découpés
    selon le format demandé *)
(* ===================================================================== *)
let of_bin_file taille lg_mot filename = 
  let code = BoolArray.of_bin_file filename in
  of_bool_array taille lg_mot code

(* ===================================================================== *)
(** Lire une matrice bool dans un <b><i>fichier ascii</i></b>
    @param taille le nombre de cases mémoire souhaitée
    @param lg_mot la longueur des mots mémoires en nombre de bit
    @param filename le nom du fichier ascii contenant les bits ('0' et '1')
    @return m une matrice mémoire fraiche contenant les bits du fichier découpés
    selon le format demandé *)
(* ===================================================================== *)
let of_asci_file taille lg_mot filename = 
  let code = BoolArray.of_asci_file filename in
  of_bool_array taille lg_mot code

(* ===================================================================== *)
(** Ecrire une matrice booléenne linéairement dans un <b><i>fichier asci</b></i> 
    @param ram une matrice mémoire
    @param filename le nom du fichier à ouvrir en écriture *)
(* ===================================================================== *)
let to_asci_file ram filename = 
  let taille = Array.length ram and lg_mot = Array.length ram.(0) in
  let oc = open_out filename in
  for i = 0 to pred taille do
    for j = 0 to pred lg_mot do
      Printf.fprintf oc "%c" (if ram.(i).(j) then '1' else '0');
    done;
    Printf.fprintf oc "\n"
  done;
  flush oc;
  close_out oc

(* ===================================================================== *)
(** Ecrire une matrice booléenne linéairement dans un <b><i>fichier binaire</b></i> 
    @param ram une matrice mémoire
    @param filename le nom du fichier à ouvrir en écriture *)
(* ===================================================================== *)
let to_bin_file ram filename = 
  let taille = Array.length ram and lg_mot = Array.length ram.(0) in
  let oc = Bit.bopen_out filename in
  for i = 0 to pred taille do
    for j = 0 to pred lg_mot do
      Bit.bwrite oc ram.(i).(j)
    done;
  done;
  Bit.bclose_out oc

(* ===================================================================== *)
(** Ecrire une matrice booléenne linéairement dans un <b><i>channel ascii</b></i> 
    @param ram une matrice mémoire
    @param oc le channel *)
(* ===================================================================== *)
let to_asci_channel ram oc = 
  let taille = Array.length ram and lg_mot = Array.length ram.(0) in
  for i = 0 to pred taille do
    for j = 0 to pred lg_mot do
      Printf.fprintf oc "%c" (if ram.(i).(j) then '1' else '0');
    done;
    Printf.fprintf oc "\n"
  done;
  flush oc

(* ===================================================================== *)
(** Ecrire une matrice booléenne linéairement dans un <b><i>channel binaire</b></i> 
    @param ram une matrice mémoire
    @param oc le channel *) 
(* ===================================================================== *) 
let to_bin_channel ram ocf = 
  let taille = Array.length ram and lg_mot = Array.length ram.(0) in
  let oc = Bit.bopen_out_channel ocf in
  for i = 0 to pred taille do
    for j = 0 to pred lg_mot do
      Bit.bwrite oc ram.(i).(j)
    done;
  done;
  Bit.bclose_out_channel oc (* ne ferme pas ocf *)

(* ===================================================================== *)

